--
-- Cambios para que la variable de precios pueda contener funciones dentro del cálculo.
-- Además se corrigió un error que reemplazaba las variables en la fórmula por sus valores con un reemplazo simple
-- tal que no podía haber dos variables que comenzaran igual (PRE y PRE2 por ej.)
--

CREATE OR REPLACE FUNCTION pre_eval(
    character varying,
    character varying)
  RETURNS numeric AS
$BODY$  
DECLARE
formulaStr	  ALIAS FOR $1;
valorNUMERAL_CANT ALIAS FOR $2;
formulaFinal	VARCHAR;
cadena		VARCHAR;
resultado	NUMERIC;

BEGIN
formulaFinal := REPLACE(formulaStr, '#CANT', valorNUMERAL_CANT);

-- Si #PULTV y #PULTC llegaron acá es porque estamos en un entorno sin contexto
-- y sin contexto el precio de ultima compra efectiva no está definido ponto 1 porque
-- cero pondría el precio de venta y podría confundir al pobre usuario.

--formulaFinal := REPLACE(formulaFinal, '#PULTV', ' 1.00 ');
--formulaFinal := REPLACE(formulaFinal, '#PULTC', ' 1.00 ');

formulaFinal := public.pre_preprocesoFunciones(formulaFinal);

cadena := 'SELECT ' || formulaFinal;
EXECUTE cadena INTO resultado;
RETURN resultado;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION pre_eval(character varying, character varying)
  OWNER TO abacouser;


-- Function: pre_esvblepre(character varying)

-- DROP FUNCTION pre_esvblepre(character varying);

CREATE OR REPLACE FUNCTION public.pre_essimbolo(character varying)
  RETURNS boolean AS
$BODY$

DECLARE

caracter ALIAS FOR $1;

BEGIN

IF caracter IN ('+', '-', '/', '*', '(', ')', ' ','\n', '<', '>', '=', ';', '@') THEN

RETURN TRUE;

ELSE

RETURN FALSE;

END IF;

END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.pre_essimbolo(character varying)
  OWNER TO abacouser;


CREATE OR REPLACE FUNCTION public.pre_parsearformula(
    character varying,
    character)
  RETURNS character varying AS
$BODY$
DECLARE
formula		ALIAS FOR $1;
charSeparador   ALIAS FOR $2;
formulaParseada	VARCHAR;
formulaEntrada  VARCHAR;
parte		VARCHAR;
desde		INTEGER;
hasta		INTEGER;
BEGIN
formulaParseada := '';
formulaEntrada  := formula;
WHILE (LENGTH(formulaEntrada) > 0) LOOP
BEGIN
  parte := pre_ObtenerParteFormula(formulaEntrada); 
  IF (pre_EsVblePRE(parte)) THEN
    formulaParseada := formulaParseada || parte || charSeparador;		
  END IF;
  desde := Length(parte) + 1; 
  hasta := Length(formulaEntrada) - Length(parte);
  formulaEntrada := SUBSTR(formulaEntrada, desde, hasta);
END;
END LOOP;

RETURN formulaParseada;	

END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.pre_parsearformula(character varying, character)
  OWNER TO abacouser;


CREATE OR REPLACE FUNCTION public.pre_obtenerformulainfo(
    IN character varying,
    IN integer,
    IN character varying,
    IN character varying,
    IN character varying,
    IN character varying,
    IN character varying,
    IN integer,
    IN character varying,
    IN character varying,
    IN character varying,
    IN character varying,
    IN character varying,
    IN character varying,
    IN integer,
    IN character,
    OUT character varying,
    OUT character varying)
  RETURNS SETOF record AS
$BODY$

DECLARE

formulaEntrada	 ALIAS FOR $1;

id_ART	 	 ALIAS FOR $2;

fechaEntrada	 ALIAS FOR $3;

Ctxt_TIPOPREPAGA ALIAS FOR $4;

Ctxt_CODPREPAG   ALIAS FOR $5;

Ctxt_TIPOPADA    ALIAS FOR $6;

Ctxt_CODPADR     ALIAS FOR $7;

Ctxt_IDPAD       ALIAS FOR $8;

Ctxt_TIPOARTA    ALIAS FOR $9;

Ctxt_CODARTR     ALIAS FOR $10;

Ctxt_FECHAINI    ALIAS FOR $11;

Ctxt_FECHAFIN    ALIAS FOR $12;

Ctxt_CODSUC      ALIAS FOR $13;

CodAmbTur        ALIAS FOR $14;

NroCierre        ALIAS FOR $15;

InfoFormula      ALIAS FOR $16;

--=== parÃ¡metros de salida

pout_Formula        ALIAS FOR $17;

pout_InfoFormula    ALIAS FOR $18;

formulaOriginal	VARCHAR;

formulaReemplazada  	VARCHAR;

formulaFinal  	VARCHAR;

infoFinal  	        VARCHAR;

separador		INTEGER;

valorVble		VARCHAR;

infoVble		VARCHAR;

vble			VARCHAR;

longitud 		INTEGER;

i 			INTEGER;

charSeparador		CHAR;

BEGIN

charSeparador := '-';

formulaOriginal := formulaEntrada;

--parsear formula

formulaReemplazada := pre_ParsearFormula(formulaOriginal, charSeparador);

IF (COALESCE(formulaReemplazada, '') = '') OR (formulaReemplazada = charSeparador) THEN

BEGIN

pout_Formula := formulaOriginal;

pout_InfoFormula := InfoFormula;

RETURN NEXT; --agrega los datos al conjunto resultado de salida

RETURN;

--============================

END;

END IF;

longitud := LENGTH(formulaReemplazada);

formulaFinal := formulaOriginal;

InfoFinal    := infoFormula;

--recorro en formulaReemplazada para recuperar las distintas vbles

i := 1;

WHILE i <= longitud LOOP

BEGIN

separador := POSITION(charSeparador in formulaReemplazada);

/*cuando (separador = longitud) la formula es del tipo VTA-*/

IF (separador > 0) and (separador < longitud) THEN

BEGIN

vble := SUBSTR(formulaReemplazada, 1 , separador-1);	

formulaReemplazada := SUBSTR(formulaReemplazada, separador + 1, longitud);

i := separador + 1;

END;			

ELSE BEGIN

vble := REPLACE(formulaReemplazada, '-', '');

i := longitud + 1;

END;

END IF;

IF vble <> '' THEN

BEGIN

SELECT * FROM pre_ObtenerValorInfo(vble, id_ART, 

fechaEntrada, Ctxt_TIPOPREPAGA, Ctxt_CODPREPAG,

Ctxt_TIPOPADA, Ctxt_CODPADR, Ctxt_IDPAD, 

Ctxt_TIPOARTA, Ctxt_CODARTR, 

Ctxt_FECHAINI, Ctxt_FECHAFIN, Ctxt_CODSUC, 

CodAmbTur, NroCierre)

INTO valorVble, infoVble;



formulaFinal := public.pre_reemplazar_valor_variable(formulaFinal, vble, valorVble);


if (COALESCE(InfoFinal, '') = '') AND (COALESCE(InfoVble, '') <>'') THEN

InfoFinal := infoVble;

END IF;

END;

END IF;

END;			

END LOOP;

-- retornar parÃ¡metros de salida as record

pout_Formula := formulaFinal;

pout_InfoFormula := InfoFinal;

RETURN NEXT; --agrega los datos al conjunto resultado de salida

RETURN;

END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION public.pre_obtenerformulainfo(character varying, integer, character varying, character varying, character varying, character varying, character varying, integer, character varying, character varying, character varying, character varying, character varying, character varying, integer, character)
  OWNER TO abacouser;


-- NUEVAS 

CREATE OR REPLACE FUNCTION public.pre_reemplazar_valor_variable(character varying, character varying, character varying) 
   RETURNS character varying AS
$BODY$
DECLARE
  formulaOriginal  ALIAS FOR $1;
  variable         ALIAS FOR $2;
  valorVariable    ALIAS FOR $3;
  formulaFinal     varchar;
  token            varchar;
BEGIN
  formulaFinal := ''; 
  LOOP
    IF (LENGTH(formulaOriginal) = 0) THEN EXIT; END IF;

    Token := pre_obtenerParteFormula(formulaOriginal);

    IF (Token = variable) THEN
       formulaFinal := formulaFinal || valorVariable;
    ELSE
       formulaFinal := formulaFinal || Token;
    END IF;

    formulaOriginal := substring(formulaOriginal, length(token) + 1, 100000);
  
  END LOOP;
  RETURN formulaFinal;
   
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.pre_reemplazar_valor_variable(character varying, character varying, character varying)
  OWNER TO abacouser;


CREATE OR REPLACE FUNCTION pre_preprocesofunciones(character varying)
  RETURNS character varying AS
$BODY$  
DECLARE
 formulaFinal ALIAS FOR $1;
 funcionDesdeFuncion integer;
 funcionLongitud integer;
 funcionDesdeArgumentos integer;
 funcionLongitudArgumentos integer;

 inicioVariable integer;
 finVariable    integer;
 idVariable     integer;
 codVariable    varchar;
 

 resultado numeric(15,4);
 cadenaResultado varchar;
 i_split integer;
BEGIN
 -- Cambio las variables de precio por su ID.
  LOOP
    IF POSITION('#' in formulaFinal) = 0 THEN EXIT; 
    END IF;
      inicioVariable := position('#' in formulaFinal); 
      finVariable    := position('#' in substring(formulaFinal,inicioVariable + 1, 10000)) + inicioVariable;   
      codVariable    := substring(formulaFinal,inicioVariable + 1, finVariable - inicioVariable - 1); 
      idVariable     := (SELECT ID FROM PRE WHERE COD = codVariable); 
      formulaFinal   := substring(formulaFinal,0,inicioVariable) || to_char(idVariable, 'FM9999') || substring(formulaFinal, finVariable + 1, 10000);
  END LOOP;
  LOOP
  IF (position('@' in formulaFinal) = 0) THEN EXIT; 
  END IF;
  funcionDesdeFuncion    := position('@' IN formulaFinal);
  funcionLongitud        := position('@' IN substring(formulaFinal, funcionDesdeFuncion + 1, length(formulaFinal)));
  funcionDesdeArgumentos    := position('(' in substring(formulaFinal, funcionDesdeFuncion, length(formulaFinal))) + funcionDesdeFuncion;
  funcionLongitudArgumentos := position('@' IN substring(formulaFinal, funcionDesdeArgumentos + 1, length(formulaFinal))) - 2;
  i_split := 1;
  cadenaResultado := '';
  LOOP
    IF (split_part(substring(formulaFinal, funcionDesdeArgumentos, funcionLongitudArgumentos + 1),';',i_split)) = '' THEN EXIT;
    END IF;
    IF es_entero(split_part(substring(formulaFinal, funcionDesdeArgumentos, funcionLongitudArgumentos + 1),';',i_split)) THEN 
       cadenaResultado := cadenaResultado || split_part(substring(formulaFinal, funcionDesdeArgumentos, funcionLongitudArgumentos + 1),';',i_split) || ',';
    ELSE
       EXECUTE 'SELECT ' || split_part(substring(formulaFinal, funcionDesdeArgumentos, funcionLongitudArgumentos),';',i_split) INTO RESULTADO;
       cadenaResultado := cadenaResultado || cast(resultado as varchar) || ',';
    END IF;
    i_split := i_split + 1; 
  END LOOP;
   
  formulaFinal := replace(substring(formulaFinal, 0, funcionDesdeArgumentos),'@',' ') || substring(cadenaResultado, 0, length(cadenaResultado))  || ')' || 
                  replace(substring(formulaFinal, funcionDesdeFuncion + funcionLongitud + 1, 10000),'@',' ');

END LOOP;

  return formulaFinal; 

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION pre_preprocesofunciones(character varying)
  OWNER TO abacouser;


SELECT aaVersion('430.01','430.00');